<template>
  <div class="graph">
    <svg class="svgContainer"></svg>
    <div class="g-right"></div>
    <div class="g-left">
      <el-input v-model="searchText" style="max-width: 600px" placeholder="" class="input-with-select" size="large">
        <template #prepend>
          <el-select v-model="selectType" placeholder="Select" style="width: 115px" size="large">
            <el-option label="全部" value="1" />
            <el-option label="人物" value="2" />
            <el-option label="事件" value="3" />
            <!-- <el-option label="地点" value="4" /> -->
          </el-select>
        </template>
        <template #append>
          <el-button @click="handleSearch" :icon="Search" />
        </template>
      </el-input>
    </div>
  </div>
</template>
<script lang="ts" setup>
import * as FormApi from '@/api/knowledge/character'
import * as d3 from 'd3'
import { useRoute } from 'vue-router'
import { Search } from '@element-plus/icons-vue'
import { useAppStore } from '@/store/modules/app'
import characterImg from '@/assets/imgs/character.png'
import characterFocusImg from '@/assets/imgs/character-focus.png'
import positionImg from '@/assets/imgs/position.png'
import positionFocusImg from '@/assets/imgs/position-focus.png'
import locationImg from '@/assets/imgs/location.png'
import locationFocusImg from '@/assets/imgs/location-focus.png'
const route = useRoute()
const appStore = useAppStore()
appStore.setFooter(false) // 配置当前页面不显示底部版权信息
var ckmData = reactive([]) // 图谱下所有关系数据
var ckmDataCopy = reactive([]) // 图谱下所有关系数据，复制一份用作过滤使用
const searchText = ref('') // 搜索文本
const selectType = ref('1') // 选择类型
const getTableData = () => {
  // const params = { graphName: '测试图谱知识库' }
  const params = { graphName: route.query.graphName, featureReleaseStatus:1 }
  FormApi.findNeo4jByEntity(params).then((res) => {
    Object.assign(ckmData, res)
    Object.assign(ckmDataCopy, res)
    init(ckmData)
  })
}
onMounted(() => {
  getTableData()
})
watch(
  () => selectType.value,
  (newValue, oldValue) => {
    console.log('newValue', newValue, oldValue)
    if (newValue === '1') ckmData = ckmDataCopy
    if (newValue === '2') ckmData = ckmDataCopy.filter((item) => item.endEntityType === 'person')
    if (newValue === '3') ckmData = ckmDataCopy.filter((item) => item.endEntityType === 'event')
    if (newValue === '4') ckmData = ckmDataCopy.filter((item) => item.endEntityType === 'event')
    resettingDOM()
  }
  // { immediate: true, deep: true }
)
/**
 * @description: 重置销毁g元素，再次初始化，实现数据更新效果
 * @return {*}
 * @author: 叶世超
 */
const resettingDOM = () => {
  let svg = d3.select(window.document.querySelector('.svgContainer'))
  let g = svg.select('g')
  g.data([]).exit().remove()
  init(ckmData)
}
const handleSearch = () => {
  const params = {
    entity: searchText.value,
    graphName: route.query.graphName,
    featureReleaseStatus:1
  }
  FormApi.findNeo4jSlurByEntity(params).then((res) => {
    ckmData = res
    resettingDOM()
  })
}
function init(ckmData) {
  function genNodesMap(data) {
    const hash = {}
    data.forEach((item) => {
      // 当页面渲染节点数据为父子数据对中的父数据时，数据处理
      hash[item.startEntityId] = {
        id: item.startEntityId,
        name: item.startEntity,
        fatherArray: data.filter((i) => i.endEntity === item.startEntity || i.startEntity === route.query.graphName)
          .map((item) => item.startEntity),
        sonArray: data.filter((i) => i.startEntity === item.startEntity).map((item) => item.endEntity),
        ...item
      }
      // 当页面渲染节点数据为父子数据对中的子数据时，数据处理
      hash[item.endEntityId] = {
        id: item.endEntityId,
        name: item.endEntity,
        fatherArray: data.filter((i) => i.endEntity === item.endEntity).map((item) => item.startEntity),
        sonArray: data.filter((i) => i.startEntity === item.endEntity).map((item) => item.endEntity),
        // sonArray: data.reduce((acc, current) => {
        //   const key = current.startEntity
        //   if (key === item.endEntity) {
        //     acc[key] = acc[key] || []
        //     acc[key].push( item.endEntity)
        //     return acc
        //   }
        // }, {}),
        ...item
      }
      console.log(item)
    })
    return hash
  }
  let svg = d3.select(window.document.querySelector('.svgContainer'))
  let g = svg.append('g')
  // 设置g元素的初始位置
  svg.call(
    d3.zoom().on('zoom', function (current) {
      console.log('current：', current)
      g.attr('transform', `translate(${current.transform.x},${current.transform.y}) scale(${current.transform.k})`)
    })
  )
  var nodesMap = genNodesMap(ckmData)
  console.log('nodesMap：', nodesMap)
  var nodesData = Object.values(nodesMap)
  console.log('nodesData：', nodesData)
  // 构建 links（source 属性必须从 0 开始）
  var edges = genLinks(ckmData)
  console.log('edges：', edges)
  // 新建一个力导向图
  let forceSimulation = d3
    .forceSimulation()
    // 使用指定的链接和缺省参数创建新的链接力。如果未指定 links，则默认为空数组。
    .force(
      'link',
      d3.forceLink(edges).distance(function (d) {
        return d.value * 100
      })
    )
    // 正值导致节点相互吸引，类似于重力，而负值导致节点相互排斥，类似于静电荷，默认值-30
    .force('charge', d3.forceManyBody().strength(-200))
    // 创建具有指定 x 和 y 坐标的新中心力。如果未指定 x 和 y，则默认为 ⟨0,0⟩。
    .force('center', d3.forceCenter(750, 300))
  // 生成节点数据
  forceSimulation.nodes(Object.values(nodesMap))
  // 使用 forceCollide 防止节点重叠（节点半径便不会发生重叠，如果有文字，直接直径）
  forceSimulation.force(
    'collide',
    d3
      .forceCollide()
      .radius(function () {
        return 40 // 数值越大，边就越长
      })
      .iterations(1)
  )
  // 箭头
  g.append('g')
    .attr('class', 'showLine')
    .append('marker')
    .attr('id', 'resolved')
    // .attr("markerUnits","strokeWidth") // 设置为strokeWidth箭头会随着线的粗细发生变化
    .attr('markerUnits', 'userSpaceOnUse')
    .attr('viewBox', '0 -5 10 10') // 坐标系的区域
    .attr('refX', 21) // 箭头坐标
    .attr('refY', 0)
    .attr('markerWidth', 10) // 标识的大小
    .attr('markerHeight', 10)
    .attr('orient', 'auto') // 绘制方向，可设定为：auto（自动确认方向）和 角度值
    .attr('stroke-width', 1) // 箭头宽度
    .append('path')
    .attr('d', 'M0,-5L10,0L0,5') // 箭头的路径
    .attr('fill', '#53a0ff') // 箭头颜色
  // 绘制边
  var links = g
    .append('g')
    .selectAll('path')
    .data(edges)
    .enter()
    .append('path')
    .attr('d', (link) => {
      genLinkPath(link)
    }) // 遍历所有数据。d表示当前遍历到的数据，返回绘制的贝塞尔曲线
    .attr('id', (d, i) => {
      // return 'edgepath' + d.id
      return 'line' + d.index
    }) // 设置id，用于连线文字
    .style('stroke', '#53a0ff') // 颜色
    .style('fill', 'none') // 粗细
    .style('stroke-width', 2) // 粗细
    .attr('class', 'lines')
    .attr('marker-end', 'url(#resolved)') // 根据箭头标记的id号标记箭头


  // 边上的文字
  var linksText = g
    .append('g')
    .attr('class', 'linkTextGroup')
    // .selectAll('textPath')
    .selectAll('text')
    .exit().remove()
    .data(edges)
    .enter()
    .append('text')
    .attr('dy', -5)

    // .enter()
    // .append('textPath')
    .attr('startOffset', '50%')
    // .attr('transform', `rotate(90deg)`)
    .attr('class', 'linksText')
    .attr('id', (d) => { return 'linkText' + d.index })

    // .attr('dy', 40)
    // .attr('text-anchor', 'middle')
    // .attr('display', 'absolute')

    // 连线文字角度
    // .attr('transform', (d) => {
    //   // return 'rotate(9' + ')'

    //   if (d.target.x > d.source.x) {
    //     // const { x, y, width, height } = window.document.getElementById('linkText' + d.index).getBBox()
    //     // const rx = x + width / 2
    //     // const ry = y + height / 2
    //     // return 'rotate(180 ' + rx + ' ' + ry + ')'
    //     return 'rotate(180deg' + ')'
    //   } else {
    //     return 'rotate(0)'
    //   }
    // })

    // dx、dy是相对于(x,y)的偏移
    // .attr('x', function (d) { return d.source.x })
    // .attr('dx', function (d) { return d.source.x - d.target.x })
    // .attr('dx', function (d) { return d.target.x - d.source.x })
    // .attr('dx', function (d) { return '10px' })
    // .attr('dy', function (d) { return d.target.y - d.source.y })
    // .attr('dy', function (d) { return d.target.y})
    // .attr('y', function (d) { return d.source.y })
    // .text(function (d) { return d.relations })

    // .attr("y", 0)
    // .attr("x", 9)

    // .attr('dy', (d) => {
    //   // return 'rotate(180' + ')'
    //   console.log(d)
    //   if (d.source.x > d.target.x) {
    //     // const { x, y, width, height } = window.document.getElementById('linkText' + d.index).getBBox()
    //     // const rx = x + width / 2
    //     // const ry = y + height / 2
    //     // return 'rotate(180 ' + rx + ' ' + ry + ')'
    //     return '50'
    //   } else {
    //     return 'rotate(0)'
    //   }
    // })
    // .attr('dx', (d) => {
    //   // return 'rotate(180' + ')'
    //   console.log(d)
    //   if (d.source.x > d.target.x) {
    //     // const { x, y, width, height } = window.document.getElementById('linkText' + d.index).getBBox()
    //     // const rx = x + width / 2
    //     // const ry = y + height / 2
    //     // return 'rotate(180 ' + rx + ' ' + ry + ')'
    //     return '-10'
    //   } else {
    //     return 'rotate(0)'
    //   }
    // })
    //旋转x轴label
    // .attr("transform", "rotate(180)")
    .style("text-anchor", "start")
    // .attr("transform", "rotate(180 0 0)")

    .style('font-size', 10)
    // .style('dominant-baseline', 'text-before-edge')
    // .style('dominant-baseline', 'text-before-edge')
    .style('color', 'red')
    // .attr('dy', -5)
    .style('font-size', 12)
  // .attr('transform-origin', 'center center')
  // .attr('transform', 'scale(0.5) translate(-100%, -100%)')
  // .attr('transform', 'rotate(180)')
  // .attr("font-family", "sans-serif")
  // .attr("font-size", "11px")
  // .attr("fill", "black")
  // transform:translate3d(x,y,z);
  // .attr('transform', 'translate(-250.4565559472063/-2,40.1155248582661/2)')
  // .attr('transform-origin', 'top left')
  // transform="rotate(180 305.79534912109375 347.702880859375)"
  // .attr('transform', `rotate(${180}`)

  // .merge(linksText)
  // .attr('transform', (d) => {
  //   // return 'rotate(90' + ')'
  //   console.log(d)
  //   if (d.source.x > d.target.x) {
  //     // const { x, y, width, height } = window.document.getElementById('linkText' + d.index).getBBox()
  //     // const rx = x + width / 2

  // let linksTextDOM = window.document.querySelector('.linksText')

  // 假设已经有一个包含文本的元素，例如：<div id="text">需要翻转的文字</div>
  // console.log(document.querySelector('#linkText0').getBBox())
  // console.log(document.querySelectorAll('.linksText').getBBox())
  // 选择文本元素
  var text = d3.select("#text");
  // d3.select(".linksText").style("transform", "translate(180) rotate(180deg)")
  // 使用attr方法设置transform属性实现翻转
  // text.attr("transform", "rotate(180)");
  linksText.selectAll('.textPath').remove()
  // linksText
  //   .attr('transform', (d) => {
  //     // return 'rotate(90' + ')',
  //     // return 'rotate(180' + 250.4565559472063 / 2 + '' + 40.1155248582661 / 2 + ')'

  //     // console.log(document.getElementById("wrapper").getBBox());
  //     // var linkTextGroup222 = window.document.querySelector('.linkTextGroup').getBBox()
  //     // console.log(linkTextGroup222)
  //     console.log(d)
  //     if (d.source.x > d.target.x) {
  //       const { x, y, width, height } = document.getElementById('linkText' + d.index).getBBox()
  //       // var groupElement = window.document.querySelector('#linkText' + d.index)
  //       // console.log(groupElement)
  //       // const { x, y, width, height } = groupElement.getBBox();
  //       console.log(window.document.getElementById('linkText' + d.index))
  //       console.log(x, y, width, height)
  //       const rx = x + width / 2
  //       const ry = y + height / 2
  //       console.log(rx, ry)
  //       return 'rotate(180' + ' ' + rx + ' ' + ry + ')'
  //       // return 'rotate(180' + 250.4565559472063 / 2 + '' + 40.1155248582661 / 2 + ')'

  //       //     // return 'rotate(180' + ')'
  //       //     // return `rotate(180, ${d.source.x}, ${-150})`

  //     } else {
  //       return 'rotate(0)'
  //     }
  //   })
  let textPath = linksText.append('textPath')
    // .attr("transform", "rotate(180)")
    .attr('id', (d) => { return 'textPath' + d.index })
    .attr('class', 'textPath')

    .attr('startOffset', '30%')
    // .attr('class', (d) => { return 'textPath linetext-' + d.entire.types })
    .attr('xlink:href', (d) => {
      console.log(d)
      return '#line' + d.index
    })
    // .attr('transform', (d) => {
    //   // return 'rotate(90' + ')',
    //   // return 'rotate(180' + ',' + 'translate' + (250.4565559472063 / 2 + ',' + 40.1155248582661 / 2) + ')'

    //   console.log(d)
    //   if (d.source.x > d.target.x) {
    //     const { x, y, width, height } = window.document.getElementById('textPath' + d.index).getBBox()
    //     console.log(window.document.getElementById('linkText' + d.index))
    //     console.log(x, y, width, height)
    //     const rx = x + width / 2
    //     const ry = y + height / 2
    //     console.log(rx, ry)
    //     return 'rotate(180 ' + rx + ' ' + ry + ')'
    //     // return 'rotate(180' + ')'
    //     // return `rotate(180, ${d.source.x}, ${-150})`

    //   } else {
    //     return 'rotate(0)'
    //   }
    // })
    // .text((d) => { return d.entire.id })
    .text(function (d) { return d.relations })
    .style('font-size', 10)
    .style('white-space', 'inherit')
    .style('color', 'red')
  // .attr({ 'dx': d => getLineTextDx(d) }); function getLineTextDx(d) {
  //   const sr = d.radius; const sx = d.source.x; const sy = d.source.y;
  //   const tx = d.target.x; const ty = d.target.y;
  //   const distance = Math.sqrt(Math.pow(tx - sx, 2) + Math.pow(ty - sy, 2));
  //   const textLength = d.alllabel.length; const deviation = 8;
  //   // 调整误差
  //   // const dx = (distance - sr - textLength * lineTextFontSize) / 2 + deviation; return dx;
  // }
  // linksText

  let linksTextDOM = d3.select(".textPath")
  textPath
  // .attr('transform-origin', 'center center')
  // .attr('transform', 'rotate(180)')
  // var text = d3.select(".linksText");
  // text
  // .attr('transform-origin', 'center')
  // .attr('transform', (d) => {
  //   return 'rotate(180' + ',' + (d.source.x + d.target.x) / 2 + ',' + (d.source.y + d.target.y) / 2 + ')'
  //   console.log(d)
  //   if (d.source.x > d.target.x) {
  //     // const { x, y, width, height } = window.document.getElementById('linkText' + d.index).getBBox()
  //     // const rx = x + width / 2
  //     // const ry = y + height / 2
  //     // return 'rotate(180 ' + rx + ' ' + ry + ')'
  //     return 'rotate(180' + ')'
  //   } else {
  //     return 'rotate(0)'
  //   }
  // })

  // textPath
  //   .attr('transform-origin', 'center')
  //   .attr('transform', (d) => {
  //     return 'rotate(50' + ')'

  //     if (d.target.x > d.source.x) {
  //       // const { x, y, width, height } = window.document.getElementById('linkText' + d.index).getBBox()
  //       // const rx = x + width / 2
  //       // const ry = y + height / 2
  //       // return 'rotate(180 ' + rx + ' ' + ry + ')'
  //       return 'rotate(180deg' + ')'
  //     } else {
  //       return 'rotate(0)'
  //     }
  //   })
  // 假设已经有一个包含文本的元素，例如：<div id="text">需要翻转的文字</div>

  // 选择文本元素
  // var text = d3.select("#linkText1");

  // 使用attr方法设置transform属性实现翻转
  // text.attr("transform", "rotate(180 0 0)");
  // var diagonal = d3.svg.diagonal()
  //   .projection(function (d) {
  //     return [d.x, d.y];
  //   });

  // var linkEnter = svg.selectAll("path.link")
  //   .data(edges);

  // linkEnter.enter().append("path")//在指定元素之前插入一个元素
  //   .attr("class", "link")
  //   // .attr("d", diagonal)
  //   .attr("x", function (d) { return d.target.x })
  //   .attr("y", function (d) { return d.target.y })
  //   .attr("stroke", "white")
  //   .attr("marker-end", "url(#resolved)")//根据箭头标记的id号标记箭头
  //   .style("fill", "white")
  //   .style("fill-opacity", 1)
  //   // 首先为每条节点连线添加标识id
  //   .attr("id", function (d, i) {
  //     return "mypath" + i;
  //   });
  // //为连线添加文字
  // linkEnter.enter().append('text')
  //   .attr('x', 100)
  //   .attr('y', 80)
  //   .style('fill', 'green')
  //   .style('font-size', '15px')
  //   .style('font-weight', 'bold')
  //   .append('textPath')
  //   .attr({//引用路径
  //     'xlink:href': function (d, i) {
  //       return "#mypath" + i;
  //     }
  //   })
  //   .text(function (d, i) {
  //     // debugger
  //     return d.relations
  //   });


  // var node = svg.selectAll(".node")
  //   .data(nodes)
  //   .enter()
  //   .append("g")
  //   .attr("class", "node")
  //   .attr("transform", function (d) {
  //     return "translate(" + (d.source.x + -50) + "," + (d.source.y) + ")";
  //   })

  // node.append("rect")
  //   .attr("width", 100)
  //   .attr("height", 40)
  //   .attr("x", 0)
  //   .attr("y", 0)
  //   .attr("style", "fill:#2990ca;")
  //   .attr("rx", 3);

  // node.append("text")
  //   .attr("dx", function (d) {
  //     return 30;
  //   })
  //   .attr("dy", 25)
  //   .style("text-anchor", function (d) {
  //     return "middle";
  //   })
  //   .style("fill", "#fff")
  //   .text(function (d) { return d.name; });

  // node.append("text")
  //   .attr("dx", function (d) {
  //     return 70;
  //   })
  //   .attr("dy", 25)
  //   .style("text-anchor", function (d) {
  //     return "middle";
  //   })
  //   .style("fill", "#fff")
  //   .text(function (d) { return d.number; });




  // let linkText = g
  //   .append('g')
  //   .selectAll('text')
  //   .data(edges)
  // linkText.exit().remove()
  // linkText = linkText.enter().append('text')
  //   .attr('class', (d) => { return 'linkText-' + d.relations })
  //   .attr('id', (d) => { return 'linkText-' + d.relations })
  //   .attr('dy', -5)
  //   .style('font-size', 12)
  //   .merge(linkText)

  // linkText.selectAll('.textPath').remove()
  // linkText.append('textPath')
  //   .attr('startOffset', '45%')
  //   .attr('class', (d) => { return 'textPath linetext-' + d.relations })
  //   .attr('xlink:href', (d) => { return '#line-' + d.relations })
  //   .text((d) => { return d.relations })



  // linksText.selectAll('.textPath').remove()
  // linksText.append('textPath')
  //   .attr('startOffset', '45%')
  //   .attr('class', (d) => { return 'textPath linetext-' + d.entire.types })
  //   .attr('xlink:href', (d) => { return '#line-' + d.entire.id + '-source-' + d.entire.source + '-target-' + d.entire.target })
  //   .text((d) => { return d.entire.id })
  // .attr('fill-opacity', 0)
  // 创建分组
  let gs = g
    .append('g')
    .selectAll('.circleText')
    .data(nodesData)
    .enter()
    .append('g')
    .attr('class', 'singleNode')
    .attr('id', function (d) {
      return 'singleNode' + d.id
    })
    .style('cursor', 'pointer')
    .attr('transform', function (d) {
      // console.log(d)
      let cirX = d.x
      let cirY = d.y
      return 'translate(' + cirX + ',' + cirY + ')'
    })
  console.log(gs)
  gs.append('image')
    .attr('xlink:href', function (d) {
      console.log(d)
      if (d.endEntityType === 'person') return characterImg
      else if (d.endEntityType === 'event') return positionImg
      else return locationImg
    })
    .attr('x', -20) // 设置图片中心点距离圆心的横向距离
    .attr('y', -20) // 设置图片中心点距离圆心的纵向距离
    // 宽高应是圆形的直径，但图片的宽高可能不是正方形，所以取宽高中较大值作为图片的宽高
    .attr('width', 40) // 设置图片的宽度，确保能够填满圆形区域
    .attr('height', 40) // 设置图片的高度，确保能够填满圆形区域
    .attr('clip-path', 'circle(70px at center)') // 使图片在圆形边界内显示
  // 节点悬浮标题
  gs.append('title').text((node) => {
    return node.name
  })
  // 节点底部文字
  gs.append('text')
    .attr('y', 35)
    .attr('text-anchor', 'middle')
    .style('font-size', 13)
    .text(function (d) {
      // console.log(d)
      if (d.name.length >= 6) return d.name.substring(0, 6) + '...'
      else return d.name
    })
  // 鼠标交互
  // gsImage
  gs.on('mouseover', function (d, i) {
    // console.log(d)
    // 显示连接线上的文字
    toggleLineText(d, true)
    toggleLine(links, d, true)
    toggleNode(gs, d, true)
  })
    .on('mouseout', function (d, i) {
      // console.log(d)
      // 隐去连接线上的文字
      toggleLineText(d, false)
      toggleLine(links, d, false)
      toggleNode(gs, d, false)
    })
    .on(
      'click',
      function (d, i) {
        // linksText.style('fill-opacity', function (edge) { if (edge.source === d) return 1 })
        const element = document.querySelector('.g-right') as HTMLElement
        element.innerText = d.srcElement.__data__.name
      },
      true
    )
    .call(d3.drag().on('start', started).on('drag', dragged).on('end', ended))

  svg.on(
    'click',
    (event) => {
      console.log(event)
      let data = d3.select(event.srcElement).datum() // 获取事件发生源的数据
      console.log(event.srcElement)
      console.log(data)
      removeSingle()
      const element = document.querySelector('.g-right') as HTMLElement
      if (!data) element.innerText = ''
    },
    true
  )
  forceSimulation.on('tick', ticked)
  function toggleLineText(currNode, isHover) {
    const currNodeData = {}
    Object.assign(currNodeData, currNode.srcElement.__data__)
    console.log(currNodeData)
    // if (isHover) {
    //   // 悬浮节点后，文本的高亮显示处理
    //   linksText.style('fill-opacity', function (edge) {
    //     console.log(edge)
    //     console.log(currNode)
    //     if (edge.source.startEntityId === currNode.srcElement.__data__.startEntityId) return 1
    //     else return .1
    //   })
    // } else linksText.style('fill-opacity', function () { return 1 })
    if (isHover) {
      // 悬浮节点后，文本的高亮显示处理
      linksText
        .style('opacity', 0.1)
        // .filter((edge) => edge.source.startEntityId === currNode.srcElement.__data__.startEntityId)
        // .filter((edge) => edge.source.startEntityId === currNode.srcElement.__data__.startEntityId)
        .filter((node) => {
          // console.log('text', node)
          if (currNodeData.name === route.query.graphName) {
            // alert('测试')
            console.log('测试测试测试测试', currNodeData.name)
            // return Object.values(node).includes(currNodeData.name) || Object.values(node.fatherArray[0]).includes(currNodeData.name)
            return Object.values(node).includes(currNodeData.name)
          } else {
            return (
              Object.values(node).includes(currNodeData.name) ||
              node.name === currNodeData.startEntity ||
              // node.name === currNodeData.fatherArray[0].startEntity
              node.name === currNodeData.fatherArray[0]
            )
          }
        })
        .style('opacity', 1)
    } else {
      linksText.style('opacity', 1)
    }
  }
  function toggleLine(linkLine, currNode, isHover) {
    const currNodeData = {}
    Object.assign(currNodeData, currNode.srcElement.__data__)
    console.log(currNodeData)
    if (isHover) {
      // 悬浮节点后，连线的高亮显示处理
      linkLine
        .style('opacity', 0.1)
        // .filter(link => Object.values(link.source).includes(currNodeData.endEntityId))
        // .filter(link => link.source.id === currNodeData.startEntityId)
        // .filter((link) => link.target.startEntityId === currNodeData.startEntityId)
        // .filter((link) => Object.values(link.target).includes(currNodeData.id))
        .filter((link) => {
          // console.log('text', link)
          if (currNodeData.name === route.query.graphName) {
            // alert('测试')
            console.log('测试测试测试测试', currNodeData.name)
            return (
              link.target.fatherArray[0] === currNodeData.name

              // Object.values(link.target).includes(currNodeData.name) ||
              // Object.values(link.target.fatherArray[0]).includes(currNodeData.name)
            )
            // return Object.values(link.target).includes(currNodeData.name)
          } else {
            // return Object.values(link.target).includes(currNodeData.name) || link.target.name === currNodeData.startEntity || link.target.name === currNodeData.fatherArray[0].startEntity
            // return Object.values(link.target).includes(currNodeData.name) || link.target.name === currNodeData.startEntity || link.target.name === currNodeData.fatherArray[0].startEntity
            // return Object.values(link.target).includes(currNodeData.name) || link.target.name === currNodeData.startEntity || link.target.name === currNodeData.fatherArray[0].startEntity
            return link.source.name === currNodeData.name || link.target.name === currNodeData.name
            // return Object.values(link.target).includes(currNodeData.name) || link.target.name === currNodeData.startEntity
            // return Object.values(link.target).includes(currNodeData.name)
            // return link.target.name === currNodeData.endEntity
            // return Object.values(link.target).includes(currNodeData.name) || link.target.name === currNodeData.endEntity || link.target.name === currNodeData.fatherArray[0].endEntity
          }
        })
        .style('opacity', 1)
      // .classed('link-active', true)
    } else {
      linkLine.style('opacity', 1)
      // .classed('link-active', false)
    }
  }
  /**
   * @description:
   * @param {*} nodeCircle gs组数据
   * @param {*} currNode 当前悬浮节点
   * @param {*} isHover 是否悬浮
   * @return {*}
   * @author: 叶世超
   */
  function toggleNode(nodeCircle, currNode, isHover) {
    console.log(nodeCircle)
    console.log(nodeCircle._groups[0])
    console.log(currNode)
    const currNodeData = {} // 当前节点数据
    Object.assign(currNodeData, currNode.srcElement.__data__)
    console.log(currNodeData)
    // console.log(currNodeData.fatherArray[0].startEntity)
    console.log(currNodeData.fatherArray)
    if (isHover) {
      // 悬浮节点后，节点的高亮显示处理
      nodeCircle
        .style('opacity', 0.1)
        // .filter((node) => node.startEntityId === currNodeData.startEntityId)
        // .filter((node) => console.log('node：', node.startEntity))
        // .filter((node) => Object.values(node).includes(currNodeData.id) || Object.values(node).includes(currNodeData.startEntityId))
        // .filter((node) => Object.values(node).includes(currNodeData.name) || (node.startEntity === currNodeData.fatherArray[0].startEntity && node.endEntity === currNodeData.fatherArray[0].endEntity))
        // .filter((node) => Object.values(node).includes(currNodeData.name) ||  Object.values(node).includes(currNodeData.startEntity))
        .filter((node) => {
          console.log('nodenodenode', node)
          // console.log(
          //   'Object.values(Object.values(node.sonArray))',
          //   Object.values(Object.values(node.sonArray))
          // )
          if (currNodeData.name === route.query.graphName) {
            // alert('测试')
            console.log('测试测试测试测试', currNodeData.name)
            return (
              node.fatherArray[0] === currNodeData.name

              // Object.values(node).includes(currNodeData.name) ||
              // Object.values(node.fatherArray[0]).includes(currNodeData.name)
            )
          } else {
            // console.log('node.sonArray', node.sonArray)
            return (
              Object.values(node).includes(currNodeData.name) ||
              node.name === currNodeData.startEntity ||
              // node.name === currNodeData.fatherArray[0].startEntity ||
              node.name === currNodeData.fatherArray[0] ||
              currNodeData.fatherArray.includes(node.name) ||
              // node.name === currNodeData.sonArray[0]
              currNodeData.sonArray.includes(node.name)
              // Object.values(node.fatherArray[0]).includes(currNodeData.name)
              // Object.values(node.fatherArray[0]).includes(currNodeData.name) ||
              // node.sonArray.filter((it) => Object.values(it).includes(currNodeData.name))
              // node.sonArray.includes(node.name)
              // Object.values(node).includes('叶剑英')
              // Object.values(node.sonArray).includes(node.sonArray)
              // Object.values(node.sonArray).includes(node.name)
              // node.name === node.sonArray
            )
          }
        })
        // .filter((node) => Object.values(node).includes(currNodeData.name) || (node.startEntity === currNodeData.fatherArray[0].startEntity && node.endEntity === currNodeData.fatherArray[0].endEntity))

        // .filter((node) => node.endEntity === currNodeData.fatherArray[0].startEntity)
        // .filter((node) => Object.values(node).includes(currNodeData.name) || node.endEntity === currNodeData.fatherArray[0].endEntity)
        // .filter((node) => console.log(currNodeData.fatherArray[0]))
        // .filter((node) => Object.values(node).includes(currNodeData.name) || node.relation.includes(currNodeData.fatherArray[0]))
        // .filter((node) => Object.values(node).includes(currNodeData.name) || Object.values(node).includes(currNodeData.fatherArray[0]))
        // .filter((node) => Object.values(node).includes(currNodeData.name))
        // .filter((node) => {
        //   console.log(Object.values(node).includes(currNodeData.id))
        // })

        // .filter((node) => Object.values(node).includes(currNodeData.id) || Object.values(node).includes(currNodeData.endEntityId) )
        // .filter(node => Object.values(node).includes(currNodeData.id))
        // .filter(node => node.startEntityId === currNodeData.id || node.endEntityId === currNodeData.id)
        .style('opacity', 1)
      // 悬浮切换图片
      if (currNode.srcElement.href) {
        console.log(currNodeData.relation)
        if (currNodeData.endEntityType === 'person')
          currNode.srcElement.href.baseVal = characterFocusImg
        else if (currNodeData.endEntityType === 'event')
          currNode.srcElement.href.baseVal = positionFocusImg
        else currNode.srcElement.href.baseVal = locationFocusImg
      }
    } else {
      nodeCircle.style('opacity', 1)
      if (currNode.srcElement.href) {
        if (currNodeData.endEntityType === 'person') currNode.srcElement.href.baseVal = characterImg
        else if (currNodeData.endEntityType === 'event')
          currNode.srcElement.href.baseVal = positionImg
        else currNode.srcElement.href.baseVal = locationImg
      }
    }
  }
  function removeSingle() {
    d3.select('.singleCircle').remove()
  }
  function genLinks(relations) {
    return relations.map(function ({ startEntityId, endEntityId, relation }) {
      return {
        source: nodesMap[startEntityId],
        target: nodesMap[endEntityId],
        relation,
        value: 1,
        relations: nodesMap[endEntityId].relation
      }
    })
  }
  // 生成关系连线路径
  function genLinkPath(link) {
    // console.log(link)
    let sx = link.source.x
    let tx = link.target.x
    let sy = link.source.y
    let ty = link.target.y
    return 'M' + sx + ',' + sy + ' L' + tx + ',' + ty
  }

  // ticked
  function ticked() {
    // 连线路径
    links.attr('d', (link) => genLinkPath(link))
    // 连线文字位置
    // linksText
    //   .attr('transform', function (d) {
    //     // console.log(d)
    //     let cirX = d.x
    //     let cirY = d.y
    //     // return 'translate(' + cirX + ',' + cirY + ')'
    //     return 'rotate(' + '90deg' + ')'
    //   })
    // .attr('dy', function (d) {
    //   return (180)
    // })
    // .attr('dx', function (d) {
    //   return (30)
    // })
    // .attr('x', function (d) {
    //   return (d.source.x + d.target.x) / 2
    // })
    //   .attr('y', function (d) {
    //     return (d.source.y + d.target.y) / 2
    //   })
    // 节点位置
    gs.attr('transform', function (d) {
      return 'translate(' + d.x + ',' + d.y + ')'
    })
  }
  // drag
  function started(event, d) {
    // if (!d3.event.active) {
    if (!event.active) {
      forceSimulation.alphaTarget(0.8).restart() // 设置衰减系数，对节点位置移动过程的模拟，数值越高移动越快，数值范围[0, 1]
    }
    // d.fx = d.x
    // d.fy = d.y
    // console.log(event)
    d.fx = event.x
    d.fy = event.y
  }
  function dragged(event, d) {
    // console.log(event)
    // console.log(event.x)
    // console.log(d)
    d.fx = event.x
    d.fy = event.y
    // d.fx = d3.event.x
    // d.fy = d3.event.y
  }
  function ended(event, d) {
    console.log(event)
    console.log(event.active)
    // if (!d3.event.active) {
    if (!event.active) {
      forceSimulation.alphaTarget(0)
    }
    d.fx = null
    d.fy = null
  }
  // linksText
  //   .attr('transform-origin', 'center center')
  //   .attr('transform', (d) => {
  //     // return 'rotate(90' + ')',
  //     // return 'rotate(180' + 250.4565559472063 / 2 + '' + 40.1155248582661 / 2 + ')'
  //     // console.log(document.getElementById("wrapper").getBBox());
  //     // var linkTextGroup222 = window.document.querySelector('.linkTextGroup').getBBox()
  //     // console.log(linkTextGroup222)
  //     console.log(d)
  //     if (d.source.x > d.target.x) {
  //       // console.log(document.getElementById('linkText' + d.index) as SVGTextElement)
  //       // console.log(document.querySelector('.linkTextGroup') as SVGTextElement)
  //       const { x, y, width, height } = document.getElementById('linkText' + d.index).getBBox()
  //       // var groupElement = window.document.querySelector('#linkText' + d.index)
  //       // var groupElement = document.querySelector('.linkTextGroup') as SVGTextElement
  //       // console.log(groupElement)
  //       // const { x, y, width, height } = groupElement.getBBox();
  //       // console.log(window.document.getElementById('linkText' + d.index))
  //       console.log(x, y, width, height)
  //       const rx = x + width / 2
  //       const ry = y + height / 2
  //       console.log(rx, ry)
  //       return 'rotate(180 ' + rx + ' ' + ry + ')'

  //       // return 'rotate(180' + 250.4565559472063 / 2 + '' + 40.1155248582661 / 2 + ')'

  //       //     // return 'rotate(180' + ')'
  //       //     // return `rotate(180, ${d.source.x}, ${-150})`

  //     } else {
  //       return 'rotate(0)'
  //     }
  //   })
  // 连线文字角度
  linksText
    .attr('transform-origin', 'center')
    .attr('transform', (d) => {
      console.log(d)
      if (d.target.x < d.source.x) {
        const { x, y, width, height } = document.getElementById('linkText' + d.index).getBBox()
        const bboxGroup = document.getElementById('linkText' + d.index).getBBox()
        console.log("x", bboxGroup.x);
        console.log("y", bboxGroup.y);
        console.log("width", bboxGroup.width);
        console.log("height", bboxGroup.height);
        console.log(x, y, width, height)
        const rx = width / 2
        const ry = height / 2
        // const rx =  x + width / -2
        // const ry = y * 10
        // const rx = x + width / 2
        // const ry = y + height / 2
        // const ry = y + height * -10
        // return 'rotate(180 ' + rx + ' ' + ry + ')'
        // return 'rotate(180 ' + ')'
      } else {
        return 'rotate(0)'
      }
    })
}
</script>
<style lang="scss" scoped>
.graph {
  height: calc(100vh - 35px - 50px - 4px);
  position: relative;
  background-image: url('@/assets/imgs/knowledgegraphBackgroundImage.jpg');
  // background-size: 100%;
  background-repeat: no-repeat;

  .svgContainer {
    width: 100%;
    height: 100%;
  }

  .g-right {
    width: 100px;
    height: 100px;
    position: absolute;
    top: 2px;
    right: 2px;
  }

  .g-left {
    position: absolute;
    top: 2px;
    left: 2px;
  }
}

.link-active {
  stroke-opacity: 1;
  stroke-width: 3;
}
</style>
